package at.irian.jsfatwork.broker.domain.account;

import at.irian.jsfatwork.broker.domain.BaseEntity;
import at.irian.jsfatwork.broker.domain.DomainModelException;
import at.irian.jsfatwork.broker.domain.client.Client;
import org.hibernate.annotations.ForeignKey;

import javax.persistence.*;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Thomas Spiegl
 */
@Entity
public class ClearingAccount extends ClientAccount {

    private String currency;

    private List<ClearingAccountPosition> clearingAccountPositions;

    @Basic(optional = false)
    public String getCurrency() {
        return currency;
    }

    public void setCurrency(String currency) {
        this.currency = currency;
    }

    @OneToMany(cascade = CascadeType.ALL)
    @ForeignKey(name = "clearing_account_id")
    public List<ClearingAccountPosition> getClearingAccountPositions() {
        return clearingAccountPositions;
    }

    public void setClearingAccountPositions(List<ClearingAccountPosition> clearingAccountPositions) {
        this.clearingAccountPositions = clearingAccountPositions;
    }

    public void validateCovered(BigDecimal amount) {
        ClearingAccountBalance balance = getClearingAccountBalance();
        if (!balance.isCovered(amount)) {
            throw new DomainModelException("Account " + getAccountNumber() + " is not covered (" + amount + " > "
                    + getClearingAccountBalanceAmount() + " )");
        }
    }

    public void credit(BigDecimal amount) {
        ClearingAccountPosition position = new ClearingAccountPosition();
        position.setBookingDateTime(new Date());
        position.setAmount(amount);
        if (clearingAccountPositions == null) {
            clearingAccountPositions = new ArrayList<ClearingAccountPosition>();
        }
        clearingAccountPositions.add(position);
    }

    public void debit(BigDecimal amount) {

        validateCovered(amount);

        ClearingAccountPosition position = new ClearingAccountPosition();
        position.setBookingDateTime(new Date());
        position.setAmount(amount.negate(MathContext.DECIMAL32));
        if (clearingAccountPositions == null) {
            clearingAccountPositions = new ArrayList<ClearingAccountPosition>();
        }
        clearingAccountPositions.add(position);
    }

    @Transient
    public BigDecimal getClearingAccountBalanceAmount() {
        return getClearingAccountBalance().getBalance();
    }

    @Transient
    private ClearingAccountBalance getClearingAccountBalance() {
        ClearingAccountBalance balance = new ClearingAccountBalance();
        for (ClearingAccountPosition position : clearingAccountPositions) {
            position.accountBalance(balance);
        }
        return balance;
    }

}
